﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using KmeansWrapper;
using MvcApplication2.Models;

namespace MvcApplication2.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        private AlgoResult lastAnswer = null;
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult RecieveFile()
        {
            if(Request.Files != null && Request.Files.Count == 1)
            {
                HttpPostedFileBase file = Request.Files[0]; //Uploaded file
                StreamReader fileContent = new StreamReader(file.InputStream);

                this.lastAnswer = this.ReadAndCalculate(fileContent);
                return Json(this.lastAnswer);
            }
            else
            {
                return Json("Upload failed");    
            }
        }

        public AlgoResult ReadAndCalculate(StreamReader file)
        {
            try
            {
                int k, n;
                string line = file.ReadLine();
                string[] words = line.Split(' ');
                n = int.Parse(words[0]);
                k = int.Parse(words[1]);

                int[] X = new int[n];
                int[] Y = new int[n];
                int[] Weight = new int[n];
                double[] centersX = new double[k];
                double[] centersY = new double[k];

                int counter = 0;

                // reading data from file
                while (!file.EndOfStream)
                {
                    line = file.ReadLine();
                    words = line.Split(' ');
                    X[counter] = int.Parse(words[0]);
                    Y[counter] = int.Parse(words[1]);
                    try
                    {
                        Weight[counter] = int.Parse(words[2]);
                    }
                    catch (IndexOutOfRangeException)
                    {
                        Weight[counter] = 1;
                    }

                    counter++;
                }

                int[] clusters = new int[n];

                AlgoResult result = new AlgoResult();
                List<IterationResult> iterations = new List<IterationResult>();
                List<Pointg> points = new List<Pointg>();
                for (int j = 0; j < X.Length; j++)
                {
                    points.Add(new Pointg { Cluster = 0, X = X[j], Y = Y[j] });
                }

                iterations.Add(new IterationResult { ClustersX = null, ClustersY = null, Points = points.ToArray() });

                unsafe
                {
                    fixed (int* pX = &X[0])
                    fixed (int* pY = &Y[0])
                    fixed (int* pWeight = &Weight[0])
                    fixed (double* pCentersX = &centersX[0])
                    fixed (double* pCentersY = &centersY[0])
                    fixed (int* pCluters = &clusters[0])
                    {
                        KMeansWrapper solver = new KMeansWrapper(pX, pY, pWeight, n, k, pCentersX, pCentersY, pCluters);
                        solver.SetCenters();

                        IterationResult iter = new IterationResult();
                        iter.ClustersX = (double[])centersX.Clone();
                        iter.ClustersY = (double[])centersY.Clone();
                        iter.Points = (Pointg[])iterations[0].Points.Clone();
                        iter.Result = -1;
                        iterations.Add(iter);

                        while (solver.PrepareNextIteration())
                        {
                            points = new List<Pointg>();
                            for (int j = 0; j < X.Length; j++)
                            {
                                points.Add(new Pointg { Cluster = clusters[j], X = X[j], Y = Y[j] });
                            }

                            IterationResult i = new IterationResult();

                            i.Result = solver.GetResult();
                            i.Points = (Pointg[])points.ToArray().Clone();
                            i.ClustersX = (double[])centersX.Clone();
                            i.ClustersY = (double[])centersY.Clone();

                            iterations.Add(i);
                        }
                    }
                }

                result.Iterations = iterations.ToArray();
                result.ScaleCoordinates();

                return result;
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
}